home *** CD-ROM | disk | FTP | other *** search
- /* AmiTrackServer.c -- a program to keep a running list of available Amigas. */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
-
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/dos_protos.h>
-
- #include <errno.h>
- #include <inetd.h>
- #include <sys/types.h>
-
- #include <proto/socket.h>
- #include <proto/exec.h>
- #include <sys/errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/syslog.h>
- #include <netdb.h>
-
- #include <pragmas/socket_pragmas.h>
- #include <devices/timer.h>
-
- #include "AmiTrackShared.h"
-
- struct Library * SocketBase = NULL;
-
- static ULONG ulPurgeDelay = AMITRACK_TIMEOUT_MINUTES * 60;
- static struct TimerStuff * Timer = NULL;
- static struct SocketStuff * TCPStuff = NULL, * UDPStuff = NULL;
- static struct ClientList * clientList = NULL;
-
- static void Cleanup(void);
- static void HandleClientRequest(struct ClientList *, struct SocketStuff * sSocket);
- static void HandleListRequest(struct ClientList *, struct SocketStuff * sSocket);
- static void PurgeOldClients(struct ClientList *);
-
- int main(int argc, char **argv)
- {
- BOOL BDone = FALSE, BPrintList;
- int nCode, nPort = SERVER_TCP_PORT;
-
- if ((argc == 2)&&(strcmp(argv[1],"?")==0))
- {
- printf("Usage: AmiTrackServer [Port]\n");
- exit(5);
- }
- atexit(Cleanup);
-
- if (argc >= 2) nPort = atoi(argv[1]);
- nPort = nPort ? nPort : SERVER_TCP_PORT;
-
- UNLESS(SocketBase = OpenLibrary("bsdsocket.library", 2))
- TrackExit("Couldn't open socket.library v2+",RETURN_ERROR);
- UNLESS(Timer = SetupTimer(NULL))
- TrackExit("Couldn't setup timer.device.",RETURN_ERROR);
- UNLESS(clientList = SetupClientList(NULL))
- TrackExit("Couldn't create client list.",RETURN_ERROR);
- UNLESS(UDPStuff = SetupSocket(NULL, nPort, SOCK_DGRAM))
- TrackExit("Couldn't setup UDP socket.",RETURN_ERROR);
- UNLESS(TCPStuff = SetupSocket(NULL, nPort, SOCK_STREAM))
- TrackExit("Couldn't setup TCP socket.",RETURN_ERROR);
- listen(TCPStuff->fd,5);
-
- Signal(FindTask(NULL),SIGBREAKF_CTRL_D);
- SetTimer(Timer, ulPurgeDelay, 0);
-
- while(nCode = TrackWait(TCPStuff, UDPStuff, Timer, NULL, NULL))
- {
- BPrintList = FALSE;
-
- if (nCode & CODE_TCP_SOCKET) HandleListRequest(clientList,TCPStuff);
- if (nCode & CODE_UDP_SOCKET)
- {
- HandleClientRequest(clientList,UDPStuff);
- BPrintList = TRUE;
- }
- if (nCode & CODE_TIMER_EXPIRED)
- {
- PurgeOldClients(clientList);
- SetTimer(Timer, ulPurgeDelay,0);
- BPrintList = TRUE;
- }
- if (nCode & CODE_REFRESH) BPrintList = TRUE;
-
- if (BPrintList)
- {
- ClearTrackScreen();
- printf("Clients currently logged in to this server (port %i):\n",nPort);
- PrintClientList(clientList);
- }
- }
- }
-
-
-
-
-
-
-
- /* Always called when AmiTrack exits, does any necessary cleanup */
- void Cleanup(void)
- {
- /* Shuts everything down (don't let the calls to Setup*() mislead you) */
- if (Timer) SetupTimer(Timer);
- if (TCPStuff) SetupSocket(TCPStuff,0,0);
- if (UDPStuff) SetupSocket(UDPStuff,0,0);
- if (clientList) SetupClientList(clientList);
- if (SocketBase) CloseLibrary(SocketBase);
- }
-
-
-
-
- /* Called when someone attempts to connect to us via a TCP stream.
- Dumps the current client list out to the connectee, then closes
- the stream so he knows we're done outputting. */
- void HandleListRequest(struct ClientList * ClientList, struct SocketStuff * sSocket)
- {
- struct hostent * hp;
- struct sockaddr_in saFrom;
- LONG sSizeOf = sizeof(struct sockaddr_in);
- LONG sNewSocket = accept(sSocket->fd, &saFrom, &sSizeOf);
- struct Client * client = (struct Client *) (ClientList->list.lh_Head);
-
- if (hp = gethostbyaddr((caddr_t)&saFrom.sin_addr, sizeof(saFrom.sin_addr), AF_INET))
- {
- printf(" \r");
- printf("Sending Client list to [%s]... \r", hp->h_name);
- fflush(stdout);
-
- /* Now send the list */
- while (client->node.ln_Succ)
- {
- send(sNewSocket, client->hostname, strlen(client->hostname)+1, 0L);
- send(sNewSocket, client->comment, strlen(client->comment) +1, 0L);
- send(sNewSocket, (char *) &client->ulIPAddress, sizeof(ULONG), 0L);
- client = (struct Client *)client->node.ln_Succ;
- }
- }
- else printf("Couldn't determine connection's origin, disconnecting.\n");
- CloseSocket(sNewSocket);
- }
-
-
- /* Go through the client list, and remove anyone who has a timestamp
- that is older than tCutoff. */
- void PurgeOldClients(struct ClientList * ClientList)
- {
- time_t tCutOff = time(NULL) - ulPurgeDelay;
- struct Client * client = (struct Client *) ClientList->list.lh_Head;
- struct Client * next;
-
- while (client->node.ln_Succ)
- {
- next = client->node.ln_Succ;
- if (client->tDateStamp < tCutOff)
- {
- Remove((struct Node *)client); FreeClient(client); ClientList->nListLength--;
- }
- client = next;
- }
- }
-
-
- /* Called when we are sent a UDP packet by some client */
- void HandleClientRequest(struct ClientList * ClientList, struct SocketStuff * sSocket)
- {
- char sRecvBuf[1500];
- static struct sockaddr_in saFrom;
- LONG lAddrSize = sizeof(struct sockaddr_in), lReqs;
- struct Client * client;
- struct hostent * hp;
- int nBufLen;
- ULONG ulIPAddress;
-
- if ((nBufLen = recvfrom(sSocket->fd, sRecvBuf, sizeof(sRecvBuf), 0L, &saFrom, &lAddrSize)) < 0)
- {
- printf("Recvfrom failed.\n");
- return;
- }
-
- hp = gethostbyaddr((caddr_t)&saFrom.sin_addr, sizeof(saFrom.sin_addr), AF_INET);
- UNLESS((hp)&&(hp->h_name))
- {
- printf("Couldn't determine packet's origin.\n");
- return;
- }
- memcpy(&lReqs, sRecvBuf, sizeof(ULONG));
- ulIPAddress = (ULONG) *((ULONG *)hp->h_addr_list[0]);
- UNLESS(client = GetClient(ClientList, ulIPAddress, hp->h_name,
- (lReqs & REQ_COMMENT) ? PastSpaces(RemoveUnprintableChars(&sRecvBuf[sizeof(ULONG)])) : NULL))
- {
- printf("Add/retrieve of client listing failed.\n");
- return;
- }
-
- if (lReqs & REQ_BYE) RemoveClient(ClientList, hp->h_name);
- client->tDateStamp = time(NULL);
- }
-
-
-
-
-
-